package com.blockchain.coupon.service.impl;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;

import com.blockchain.coupon.mapper.SettlementOperationMapper;
import com.blockchain.coupon.po.CouponRulerCustom;
import com.blockchain.coupon.rpc.Web3;
import org.springframework.beans.factory.annotation.Autowired;

import com.blockchain.coupon.mapper.ConsumerMapper;
import com.blockchain.coupon.mapper.CouponMapper;
import com.blockchain.coupon.mapper.MerchantMapper;
import com.blockchain.coupon.po.CouponApplicationCustom;
import com.blockchain.coupon.po.CouponCountInfo;
import com.blockchain.coupon.po.CouponCustom;
import com.blockchain.coupon.po.CouponInfo;
import com.blockchain.coupon.po.CouponPayApplicationCustom;
import com.blockchain.coupon.po.MerchantCustom;
import com.blockchain.coupon.po.MerchantRegisterCustom;
import com.blockchain.coupon.po.QueryCouponStatus;
import com.blockchain.coupon.po.SettlementOperationCustom;
import com.blockchain.coupon.service.MerchantService;
import com.blockchain.coupon.sha3.Sha3;
import com.blockchain.coupon.util.DateUtil;
import com.blockchain.coupon.util.Encryption;
import com.blockchain.coupon.util.ReadAccount;

public class MerchantServiceImpl implements MerchantService{
	
	@Autowired
	private MerchantMapper merchantMapper;
	
	@Autowired
	private SettlementOperationMapper settlementOperationMapper;
	
	@Autowired
	private CouponMapper couponMapper;
	
	@Autowired
	private ConsumerMapper consumerMapper;

//	插入结算券申请
	public String insertSettlementOperation(SettlementOperationCustom soc) throws Exception {
		// TODO Auto-generated method stub
		soc.setId(UUID.randomUUID().toString());
		soc.setOperationDate(DateUtil.getCurrentDate());
			
		try {
			settlementOperationMapper.insertSettlementOperation(soc);
			return "1";
		} catch (Exception e) {
			// TODO: handle exception
			return "0";
		}
	}

//	查询结算券余额
	public Integer querySettlementBalance(String merchantId) throws Exception {
		// TODO Auto-generated method stub
		return merchantMapper.querySettlementBalance(merchantId);

	}

//	商户注册
	public String insertMerchant(MerchantRegisterCustom merchantRegisterCustom) throws Exception {
		// TODO Auto-generated method stub
//		查询该用户是否已经存在
		MerchantRegisterCustom mrc=merchantMapper.queryMerchantRegInfoByAccount(merchantRegisterCustom.getAccount());
		if(mrc!=null&&mrc.getStatus().equals("1")){
			return "0";
		}
		merchantRegisterCustom.setId(UUID.randomUUID().toString());
		String salt= Encryption.createSalt();
		merchantRegisterCustom.setSalt(salt);
//		用sha3加密算法对前端传递过来的代码再次进行加密
		merchantRegisterCustom.setPassword(Sha3.sha3(merchantRegisterCustom.getPassword()+salt));
//		添加商户公钥
//		merchantCustom.setPublicKey(CreatePublicKey.create());
	
		
		try {
			merchantMapper.insertRegisterApp(merchantRegisterCustom);
			return "1";
		} catch (Exception e) {
			// TODO Auto-generated catch block
			return "0";
		}
	}

/**
 * 商户登录
 * 登录成功，返回商户id，生成token，并将token写入商户表
 */
	public Map<String, String> login(String account, String password) throws Exception {
		// TODO Auto-generated method stub
		MerchantCustom mc=merchantMapper.queryMerchantInfoByAccount(account);
		Map<String, String> m=new HashMap<String, String>();
		if(mc!=null){
			String encryptionPasswd=Sha3.sha3(password+mc.getSalt());
			if(encryptionPasswd.equals(mc.getPassword())){
				try {
					m.put("resultCode", "1");
					m.put("id", mc.getId());
					String timeStamp=DateUtil.getCurrentTime();
					String token=Sha3.sha3(account+password+timeStamp);
					m.put("token", token);
					mc.setToken(token);
					merchantMapper.updateToken(mc);
					return m;
				} catch (Exception e) {
					// 如果token指令更新失败
					m.put("resultCode", "-1");
					return m;
				}
			}else{
				m.put("resultCode", "0");
				return m;
			}
		}else{
			m.put("resultCode", "0");
			return m;
		}
	}
	
	
/**
 * 插入优惠券发行规则
 * @param couponRulerCustom
 * @return
 */
	public String insertCr(CouponRulerCustom couponRulerCustom){
		couponRulerCustom.setId(UUID.randomUUID().toString());
		couponRulerCustom.setIssueDate(DateUtil.getCurrentDate());
		try {

			/**
			 * 创建所有的智能合约,并将每一份合约写入数据库
			 * 
			 */
//			计算发行的优惠券张数
			int num=couponRulerCustom.getTotalAmount()/couponRulerCustom.getGive();
			MerchantCustom mc=merchantMapper.queryPKAndConAddr(couponRulerCustom.getMerchantId());
//			查询结算券余额，判断剩下的结算券是否足够发行优惠券
			int settlementBalance=merchantMapper.querySettlementBalance(couponRulerCustom.getMerchantId());
			if(settlementBalance<couponRulerCustom.getTotalAmount()){
				return "0";//结算券余额不够
			}
			
			String functionName3 = "Bank.setPermissions";
			String[] content3 = {"true","true",mc.getContractAddress(),ReadAccount.getAccount("bankAccount")};
			String from3 = ReadAccount.getAccount("bankAccount");
			String to3 = ReadAccount.getAccount("bankContractAddress");//bank contract address
			String tx1= Web3.sendTransactionMap(functionName3, content3, from3, to3);
			
//	        等待挖矿，产生新的区块
				String[] content4 = {tx1};
				String finish1="null";
				while(finish1.equals("null")){
					finish1 = Web3.universalCall("eth_getTransactionReceipt", null, content4, null);
				}
			
//			创建优惠券智能合约
			String tx=null;
			
			String to = mc.getContractAddress();//Merchant contract address
			int each=10;
			int tmp=num;
			while(tmp>0){
				String issueMany = "Merchant.issueMany";
				if(tmp<each){
					each=tmp;
				}
				String[] content = {couponRulerCustom.getGive()+"",couponRulerCustom.getValidStartDate(),couponRulerCustom.getValidEndDate(),each+""};
				String from = ReadAccount.getAccount("merchantAccount");
				 tx= Web3.sendTransactionMap(issueMany, content, from, to);
				 tmp=tmp-each;
			}
//			String issueMany = "Merchant.issueMany";
//			String[] content = {couponRulerCustom.getGive()+"",couponRulerCustom.getValidStartDate(),couponRulerCustom.getValidEndDate(),each+""};
//			String from = ReadAccount.getAccount("merchantAccount");
//			tx= Web3.sendTransactionMap(issueMany, content, from, to);
			
//        等待挖矿，产生新的区块
			String functionName = "eth_getTransactionReceipt";
			String[] content2 = {tx};
			String finish="null";
			while(finish.equals("null")){
				finish = Web3.universalCall(functionName, null, content2, null);
			}
			
			
//			返回所有优惠券智能合约的地址
			String getNotIssuedCoupon = "Merchant.getLatestNotIssuedCouponByQuantity";
			String[] content1 = {num+""};
			String from1 = ReadAccount.getAccount("merchantAccount");
			String to1 = to;
			String addrs=Web3.getValueMap(getNotIssuedCoupon, content1, from1, to1);
			List<String> list=Web3.decodeReturnValue("address[]", addrs);
			for(int i=0;i<num;i++){
				CouponCustom cc=new CouponCustom();
				cc.setId(UUID.randomUUID().toString());
				cc.setRulerId(couponRulerCustom.getId());
				cc.setContractAddress(list.get(i));
				cc.setOwnerId(couponRulerCustom.getMerchantId());
				cc.setCouponValue(couponRulerCustom.getGive());
				couponMapper.insertCoupon(cc);
			}
			
//			向优惠券规则表中插入一条记录
			couponMapper.insertCouponRuler(couponRulerCustom);
//			更新商户表中当前优惠券发行规则id
			merchantMapper.updateConCurrentCouponId(couponRulerCustom);
//        更新结算券余额
			MerchantCustom newMc=new MerchantCustom();
			newMc.setId(couponRulerCustom.getMerchantId());
			settlementBalance=settlementBalance-couponRulerCustom.getTotalAmount();
			newMc.setSettlementBalance(settlementBalance);
			
			merchantMapper.updateSettlementBalance(newMc);
			return "1";
		} catch (Exception e) {
			// TODO: handle exception
			return "0";
		}
	}

//	商户发行优惠券规则
	public String insertCouponRuler(CouponRulerCustom couponRulerCustom) throws Exception {
		// TODO Auto-generated method stub
//		根据商户id，查询商户最近的发行规则id
		String couponRulerId=merchantMapper.queryConCurrentCouponRulerId(couponRulerCustom.getMerchantId());
		
//     已经没有当前优惠券
		if(couponRulerId==null||couponRulerId.equals("")){
			return insertCr(couponRulerCustom);
		}else{
//			根据商户最近的发行规则id，查询发行规则信息
			CouponRulerCustom crc=couponMapper.queryCouponRulerInfo(couponRulerId);
			if(DateUtil.getCurrentDate().compareTo(crc.getValidEndDate())>0){
//				已经过了最后一次发行优惠券的有效期，可以发行新的优惠券
				return insertCr(couponRulerCustom);
			}else{
				return "0";
			}	
		}
	}

//	查询商户优惠券状态
	public List<CouponInfo> queryCouponStatus(QueryCouponStatus queryCouponStatus) throws Exception {
		// TODO Auto-generated method stub
		String couponRulerId=merchantMapper.queryConCurrentCouponRulerId(queryCouponStatus.getId());
		queryCouponStatus.setConCurrentCouponRulerId(couponRulerId);
		return couponMapper.queryCouponStatus(queryCouponStatus);
	}
	
//	查询已使用和未使用优惠券总额
	public CouponCountInfo queryTotalCoupons(String id)throws Exception{
		String couponRulerId=merchantMapper.queryConCurrentCouponRulerId(id);
		CouponCountInfo cc=couponMapper.queryTotalUsedCoupons(couponRulerId);
		int used=0;
		if(cc!=null){
			used=cc.getTotalUsedCount();
		}
		cc=couponMapper.queryTotalUnusedCoupons(couponRulerId);
		cc.setTotalUsedCount(used);
		return cc;
	}

//	查询优惠券申请
	public List<CouponApplicationCustom> queryCouponApplication(String id) throws Exception {
		// TODO Auto-generated method stub
		
		return couponMapper.queryCouponApplication(id);
	}
	

//	获取优惠券额度
	public Map<String, Integer> getCouponValue(String merchantId, String consumptionValue) throws Exception {
		// TODO Auto-generated method stub
//		根据商户id，查询当前优惠券规则id，计算应该发行的优惠券数目
		String rulerId=merchantMapper.queryConCurrentCouponRulerId(merchantId);
		CouponRulerCustom crc=couponMapper.queryCouponRulerInfo(rulerId);
		int cv=(int)Float.parseFloat(consumptionValue);
		
//		计算优惠券张数
	    int couponNum = cv/crc.getReach();
	    int couponValue=couponNum*crc.getGive();
	    
	    Map<String, Integer> m=new HashMap<String, Integer>();
		if(couponValue>crc.getCapping()){
		    m.put("couponValue", crc.getCapping());
		    m.put("couponNum", crc.getCapping()/crc.getReach());
			return m;
		}else{
		    m.put("couponValue", couponValue);
		    m.put("couponNum",couponNum);
			return m;
		}
	}
	
//	处理优惠券申请
	public String dealCouponApplicaiton(CouponApplicationCustom cac) throws Exception {
		// TODO Auto-generated method stub
//		不管商户是否拒绝优惠券申请，更新优惠券申请表状态
		if(cac.getStatus().equals("0")){
			try {
				couponMapper.updateCouponAppStatus(cac);
				return "1";
			} catch (Exception e) {
				// TODO Auto-generated catch block
				return "0";
			}
		}else{
			try {
//				判断商户剩余的优惠券是否足够支持消费者获取的优惠券
				List<CouponCustom> list=couponMapper.queryUnIssuedCoupons(cac.getMerchantId());
				if(list.size()<cac.getCouponNum()){
					return "-1";  //优惠券不够用了
				}
				String markCode=UUID.randomUUID().toString();
//				查询商户的公钥和合约地址
				MerchantCustom mc=new MerchantCustom();
				mc=merchantMapper.queryPKAndConAddr(cac.getMerchantId());
				
//			发放优惠券
//			发放优惠券,消费者合约地址来自于数据库
				String consumerContractAddress=consumerMapper.queryConsumerConAddr(cac.getConsumerId());
				String[] content = {cac.getCouponValue()+"",cac.getConsumptionValue()+"",consumerContractAddress,DateUtil.getCurrentDate()};
				String txHash=Web3.sendTransactionMap("Merchant.grant", content, mc.getPublicKey(), mc.getContractAddress());
				
				String[] content1 = {txHash};
				String finish="null";
				while(finish.equals("null")){
					finish = Web3.universalCall("eth_getTransactionReceipt", null, content1, null);
				}
//			再次获取已发放的优惠券合约地址
				String[] content2={cac.getCouponNum()+""};
				List<String> list1=Web3.decodeReturnValue("address[]", Web3.getValueMap("Merchant.getLatestIssuedCouponByQuantity", content2, mc.getPublicKey(), mc.getContractAddress()));
				for(int i=0;i<list1.size();i++){
					String couponConAddr=list1.get(i);
					CouponCustom cc=new CouponCustom();
					cc.setConsumptionDate(DateUtil.getCurrentDate());
					cc.setConsumptionValue(cac.getConsumptionValue());
					cc.setContractAddress(couponConAddr);
					cc.setMarkCode(markCode);
					cc.setStatus("2");
					cc.setOwnerId(cac.getConsumerId());
					couponMapper.updateCouponInfo(cc);
				}
//				改变优惠券申请表状态
				couponMapper.updateCouponAppStatus(cac);
				return "1";
			} catch (Exception e) {
				// TODO Auto-generated catch block
				return "0";
			}
		}

	}
	
//	查询优惠券支付申请
	public List<CouponPayApplicationCustom> queryCouponPayApp(String id) throws Exception {
		// TODO Auto-generated method stub
		return couponMapper.queryCouponPayApp(id);
	}
	
//	优惠券支付申请确认
	public String dealCouponPayApp(String id, String applicationCode) throws Exception {
		// TODO Auto-generated method stub
		try {
			couponMapper.updateCouponPayApp(applicationCode);
//		根据优惠券支付申请码查询消费者id和优惠券id
			List<CouponPayApplicationCustom> list=couponMapper.queryIdByAppCode(applicationCode);
			String consumerId=list.get(0).getConsumerId();
//		查询消费者合约地址
			String consumerContractAddress=consumerMapper.queryConsumerConAddr(consumerId);
//		根据优惠券id查询优惠券合约地址和更新优惠券状态
			StringBuilder sb=new StringBuilder();
			int addSettlementCoupon=0;
			sb.append("[");
			for(int i=0;i<list.size();i++){
				String couponId=list.get(i).getCouponId();
				addSettlementCoupon=addSettlementCoupon+list.get(i).getCouponValue();
				String contractAddress=couponMapper.queryConponConAddr(couponId);
				sb.append(contractAddress);
				if(i!=(list.size()-1)){
					sb.append(",");
				}
				CouponCustom cc=new CouponCustom();
				cc.setId(couponId);
				cc.setOwnerId(id);
				couponMapper.updateCouponInfoById(cc);
			}
			
			sb.append("]");
			String contractAddrs=sb.toString();
			MerchantCustom mc=merchantMapper.queryPKAndConAddr(id);
//		更新区块链上优惠券合约的相关状态
			String functionName = "Merchant.payConfirm";
			String[] content = {consumerContractAddress,contractAddrs};
			String from = ReadAccount.getAccount("merchantAccount");
			String to = mc.getContractAddress();//Merchant contract address
			String txHash=Web3.sendTransactionMap(functionName, content, from, to);
			
			String[] content1 = {txHash};
			String finish="null";
			while(finish.equals("null")){
				finish = Web3.universalCall("eth_getTransactionReceipt", null, content1, null);
			}
			
//			   查询和更新商户结算券余额
			int settlementBalance=merchantMapper.querySettlementBalance(id);
			settlementBalance=settlementBalance+addSettlementCoupon;
			MerchantCustom merchantCustom=new MerchantCustom();
			merchantCustom.setId(id);
			merchantCustom.setSettlementBalance(settlementBalance);
			merchantMapper.updateSettlementBalance(merchantCustom);
			return "1";
		} catch (Exception e) {
			// TODO Auto-generated catch block
			return "0";
		}
	}

}
